package cn.com.jdyun.controller;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import cn.com.jdyun.dto.TransferRecordsDTO;
import cn.com.jdyun.dto.UserCredit;
import cn.com.jdyun.exception.BdexGatewayException;
import cn.com.jdyun.exception.WarningException;
import cn.com.jdyun.interceptor.Auth;
import cn.com.jdyun.pojo.LockCoin;
import cn.com.jdyun.pojo.TransferRecords;
import cn.com.jdyun.service.LockCoinService;
import cn.com.jdyun.service.MinerService;
import cn.com.jdyun.service.TransferService;
import cn.com.jdyun.service.UserSecService;
import cn.com.jdyun.service.UserService;
import cn.com.jdyun.util.Constant;
import cn.com.jdyun.util.RedisUtil;
import cn.com.jdyun.util.WebConstants;
import cn.com.jdyun.util.reponse.Result;
import cn.com.jdyun.util.reponse.Status;

/**
 * @author admin
 * @date Created in 下午 2:10 2018/8/25 0025
 */
@RestController
public class TransactionController {

    private static final Logger logger = LoggerFactory.getLogger(TransactionController.class);

    @Autowired
    private TransferService transferService;
    @Autowired
    private MinerService minerService;
    @Autowired
    private LockCoinService lockCoinService;
    @Autowired
    private UserSecService userSecService;
    @Autowired
    private UserService userService;

    @Autowired
    RedisUtil redisUtil;

    //转账
    @Auth
    @PostMapping("/Transaction/bdexCoins")
    public Result transferFrom( String coinType, String secPassword, String amount, String to, String receivePhone, String remarks, HttpSession session) throws BdexGatewayException, WarningException, UnsupportedEncodingException {
        UserCredit userCredit = (UserCredit) session.getAttribute(Constant.ACCOUNT_Mining);
        //控制频繁操作 ，或者二次提交的问题
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if(StringUtils.isEmpty(coinType)){
            logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+""+userCredit.getId()+" 转账代币种类不能为空!" );
            throw new BdexGatewayException("转账代币种类不能为空!");
        }
        String value = coinType + secPassword + amount + to;
        String rediValue = redisUtil.hget("/Transaction/bdexCoins", userCredit.getId());
        if (rediValue != null && rediValue.equals(value)) {
            logger.error(userCredit.getId()+":交易过于频繁!");
            return Result.create(Status.FREQUENT_REQUEST, value);
        }
        redisUtil.hset("/Transaction/lockPosition", userCredit.getId(), value, 2);
        if (userCredit.getFlag() == 0) {
            if (redisUtil.exists("errorInfo:" + userCredit.getId())) {
                redisUtil.del("errorInfo:" + userCredit.getId());
            }
        }
//        UserSec userSec = userSecService.queryByUserId(userCredit.getId());
//        if (userSec == null) {
//            logger.error(userSec.getUserId()+":交易需要身份设置，交易密码设置");
//            throw new BdexGatewayException("交易需要身份设置，交易密码设置");
//        }
        if (StringUtils.isEmpty(to)) {
            logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+""+userCredit.getId()+" 转出方ID不能为空!" );
            throw new BdexGatewayException("转出方ID不能为空");
        }

        //如果没有输入交易密码跳转到身份认证
        if (StringUtils.isEmpty(secPassword)) {
            logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+""+userCredit.getId()+" 交易密码不能为空!" );
            throw new WarningException("交易密码不能为空!");
        }
        if(amount.equals("0")){
            logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+""+userCredit.getId()+" 转账金额不能为0!" );
            throw new BdexGatewayException("转账金额不能为0");
        }

        checkSecPwd(userCredit.getId(), secPassword, session);


//        if(userSec.getFlag() == 0) {
//    		throw new BdexGatewayException("请先进行实名认证", Status.ACCOUNT_SEC_ID_ERROR.getCode());
//    	}
//    	if(userSec.getFlag() == 1 && userSec.getIdCardNo() != null) {
//    		throw new BdexGatewayException("实名认证审批中", Status.ACCOUNT_SEC_ID_APPLY.getCode());
//    	}
//    	if(userSec.getFlag() == 3) {
//    		throw new BdexGatewayException("实名认证已驳回", Status.ACCOUNT_SEC_ID_REFUSED.getCode());
//    	}

        TransferRecords transferRecords = transferService.transferFrom(userCredit.getId(), to, coinType, amount, secPassword, receivePhone, remarks);
        Result r = new Result();
        if (transferRecords == null) {
            r.setMsg("交易密码输入错误5次,账号被封,请联系客服!");
        } else {
            r.setData(transferRecords);
        }
        return r;
    }


    /**
     * 查询客户代币数量
     *
     * @return
     */
    @Auth
    @PostMapping("/Transaction/inqueryCoinAmountByCoinType")
    public Result inqueryCoinAmountByCoinType(@RequestParam(required = false) String coinType, HttpSession session) throws BdexGatewayException {
        UserCredit userCredit = (UserCredit) session.getAttribute(Constant.ACCOUNT_Mining);
        Result result = new Result();
        if (StringUtils.isEmpty(coinType)) {
            coinType = Constant.COINTYPE_SSSP;
        }
        String coinAmount = minerService.inqueryCoinAmount(userCredit.getId(), coinType);

        result.setData(coinAmount);
        return result;
    }

    /**
     * 锁仓
     *
     * @param lockAmount
     * @param secPassword
     * @param session
     * @param coinType
     * @return
     */
    @Auth
    @PostMapping("/Transaction/lockPosition")
    public Result lockPosition(String lockAmount,String coinType, String secPassword, HttpSession session) throws BdexGatewayException {
        UserCredit userCredit = (UserCredit) session.getAttribute(Constant.ACCOUNT_Mining);
        if (StringUtils.isEmpty(lockAmount)) {
            throw new BdexGatewayException("请输入锁仓的数量!");
        }
        if (StringUtils.isEmpty(coinType)) {
            throw new BdexGatewayException("代币种类不能为空!");
        }
        //控制频繁操作 ，或者二次提交的问题
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String rediValue = redisUtil.hget("/Transaction/lockPosition", userCredit.getId()+coinType);
        if (rediValue != null && rediValue.equals(lockAmount)) {
            return Result.create(Status.FREQUENT_REQUEST, lockAmount);
        }
        redisUtil.hset("/Transaction/lockPosition", userCredit.getId()+coinType, lockAmount, 2);

        checkSecPwd(userCredit.getId(), secPassword, session);

        Map<String, String> result = transferService.lockPosition(userCredit.getId(),coinType, lockAmount, secPassword);

        return Result.success(result);
    }

    /**
     * 查询用户的锁仓记录
     *
     * @param session
     * @return
     * @throws Exception
     */
    @Auth
    @PostMapping("/Transaction/lockRecords")
    public Result gainsRecords( String coinType, Integer pageNumber, Integer pageSize, HttpSession session) throws Exception {

        UserCredit userCredit = (UserCredit) session.getAttribute(Constant.ACCOUNT_Mining);

        PageHelper.startPage(pageNumber, pageSize);
        if (StringUtils.isBlank(coinType)) {
            throw new BdexGatewayException("代币种类不能为空!");
        }
        Page<LockCoin> page = lockCoinService.pageData(userCredit.getId(), coinType);

        return Result.success(page.toPageInfo());
    }


    /**
     * 查询用户的转账记录
     *
     * @param session
     * @return
     * @throws Exception
     */
    @Auth
    @PostMapping("/Transaction/bdexCoinsRecords")
    public Result bdexCoinsRecords(String coinType,Integer pageNumber, Integer pageSize, HttpSession session) throws Exception {
        UserCredit userCredit = (UserCredit) session.getAttribute(Constant.ACCOUNT_Mining);
        PageHelper.startPage(pageNumber, pageSize);
        if (StringUtils.isBlank(coinType)) {
          throw new BdexGatewayException("代币种类不能为空！");
        }
        Page<TransferRecords> page = transferService.pageData(userCredit.getId(), coinType);

        return Result.success(page.toPageInfo());
    }

    /**
     * 获取用户的交易记录详情
     *
     * @param session
     * @return
     * @throws Exception
     */
    @Auth
    @PostMapping("/Transaction/detail")
    public Result detail(Integer transactionId, HttpSession session) throws Exception {

        UserCredit userCredit = (UserCredit) session.getAttribute(Constant.ACCOUNT_Mining);

        TransferRecordsDTO detail = transferService.queryTransferDetail(transactionId);
        
//        detail.setFromUserNickName(WebConstants.shadowUserName(detail.getFromUserNickName()));
//        detail.setToUserNickName(WebConstants.shadowUserName(detail.getToUserNickName()));
        detail.setFromUserNickName(detail.getFromUserNickName());
        detail.setToUserNickName(detail.getToUserNickName());
        return Result.success(detail);
    }

    //密码确认
    private Boolean checkSecPwd(String userId, String secPwd, HttpSession session) throws BdexGatewayException {
        Boolean isRightPwd = userSecService.checkSecPwd(userId, secPwd);
        if (!isRightPwd) {
            if (StringUtils.isEmpty(redisUtil.get("ERRORINFO:" + userId))) {
                //首次输入交易密码失败
                redisUtil.set("ERRORINFO:" + userId, "1");
                logger.error(userId+":输入交易密码错误,请重新输入，还剩4次重试机会!");
                throw new BdexGatewayException("输入交易密码错误,请重新输入，还剩4次重试机会!", Status.ACCOUNT_SEC_PWD_ERROR.getCode());
            } else {
                String checkPwdExist = redisUtil.get("ERRORINFO:" + userId);
                //多次输入交易密码失败
                //次数是否超过5次
                if (Integer.valueOf(checkPwdExist) == 4) {
                    userService.updateUserFlag(userId, new Byte("1"));

                    session.invalidate();
                    session.setMaxInactiveInterval(0);
                    logger.error(userId+":输入交易密码连续错误5次，账户锁定，请联系管理员!");
                    throw new BdexGatewayException("输入交易密码连续错误5次，账户锁定，请联系管理员!", Status.ACCOUNT_SEC_PWD_ERROR.getCode());
                } else if (Integer.valueOf(checkPwdExist) == 3) {
                    redisUtil.set("ERRORINFO:" + userId, 4 + "");
                    logger.error(userId+":交易密码输入错误，,还剩1次重试机会，若再次输入错误，将被封号，请确认!");
                    throw new BdexGatewayException("交易密码输入错误，,还剩1次重试机会，若再次输入错误，将被封号，请确认!", Status.ACCOUNT_SEC_PWD_ERROR.getCode());
                } else {
                    int leaveTime = 5 - Integer.valueOf(checkPwdExist) - 1;
                    redisUtil.set("ERRORINFO:" + userId, Integer.valueOf(checkPwdExist) + 1 + "");
                    logger.error(userId+":输入交易密码错误,请重新输入，还剩" + leaveTime + "次重试机会!");
                    throw new BdexGatewayException("输入交易密码错误,请重新输入，还剩" + leaveTime + "次重试机会!", Status.ACCOUNT_SEC_PWD_ERROR.getCode());
                }
            }
        } else {
            if (StringUtils.isNotEmpty(redisUtil.get("ERRORINFO:" + userId))) {
                redisUtil.del("ERRORINFO:" + userId);
            }
            return true;
        }
    }


}
